﻿// Groupon.NET C# Library
// Copyright (c) 2011 James Paul Duncan (JPaulDuncan)
// The MIT License (MIT)
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE. 
// http://www.jpaulduncan.com

using System;
using System.Collections.Generic;
using System.Xml;

namespace Groupon.Net
{
    public sealed class Deal : ModelBase
    {
        private DealTypes _type;
        private DateTime _tippedAt;
        private DealPlacementPriorities _placementPriority;
        private string _pitchHTML;
        private TextAd _textAd;
        private string _areas;
        private List<Merchant> _merchants;
        private string _sideBarImageUrl;
        private DateTime _startAt;
        private DealStatus _status;
        private bool _isNowDeal;
        private DateTime _endAt;
        private string _mediumImageUrl;
        private string _highlightsHtml;
        private int _tippingPoint;
        private string _announcementTitle;
        private bool _isSoldOut;
        private string _smallImageUrl;
        private List<string> _tags;
        private bool _shippingAddressRequired;
        private bool _isTipped;
        private string _title;
        private List<Option> _options;
        private string _id;
        private int _soldQuantity;
        private string _largeImageUrl;
        private Division _division;
        private string _dealUrl;
        private Says _says;

        public Deal()
            : base()
        {
            _textAd = new TextAd();
            _merchants = new List<Merchant>();
            _tags = new List<string>();
            _options = new List<Option>();
            _division = new Division();
            _says = new Says();
        }

        public DealTypes Type
        {
            get { return _type; }
            set { base.SetProperty<DealTypes>("Type", ref _type, value); }
        }

        public DateTime TippedAt
        {
            get { return _tippedAt; }
            set { base.SetProperty<DateTime>("TippedAt", ref _tippedAt, value); }
        }

        public DealPlacementPriorities PlacementPriority
        {
            get { return _placementPriority; }
            set { base.SetProperty<DealPlacementPriorities>("PlacementPriority", ref _placementPriority, value); }
        }

        public string PitchHTML
        {
            get { return _pitchHTML; }
            set { base.SetProperty<string>("PitchHTML", ref _pitchHTML, value); }
        }

        public TextAd TextAd
        {
            get { return _textAd; }
            set { base.SetProperty<TextAd>("TextAd", ref _textAd, value); }
        }

        public string Areas
        {
            get { return _areas; }
            set { base.SetProperty<string>("Areas", ref _areas, value); }
        }

        public List<Merchant> Merchants
        {
            get { return _merchants; }
            set { base.SetProperty<List<Merchant>>("Merchants", ref _merchants, value); }
        }

        public string SideBarImageURL
        {
            get { return _sideBarImageUrl; }
            set { base.SetProperty<string>("SidebarImageURL", ref _sideBarImageUrl, value); }
        }

        public DateTime StartAt
        {
            get { return _startAt; }
            set { base.SetProperty<DateTime>("StartAt", ref _startAt, value); }
        }

        public DealStatus Status
        {
            get { return _status; }
            set { base.SetProperty<DealStatus>("Status", ref _status, value); }
        }

        public bool IsNowDeal
        {
            get { return _isNowDeal; }
            set { base.SetProperty<bool>("IsNowDeal", ref _isNowDeal, value); }
        }

        public DateTime EndAt
        {
            get { return _endAt; }
            set { base.SetProperty<DateTime>("EndAt", ref _endAt, value); }
        }

        public string MediumImageURL
        {
            get { return _mediumImageUrl; }
            set { base.SetProperty<string>("MediumImageURL", ref _mediumImageUrl, value); }
        }

        public string HighlightsHTML
        {
            get { return _highlightsHtml; }
            set { base.SetProperty<string>("HighlightsHTML", ref _highlightsHtml, value); }
        }

        public int TippingPoint
        {
            get { return _tippingPoint; }
            set { base.SetProperty<int>("TippingPoint", ref _tippingPoint, value); }
        }

        public string AnnouncementTitle
        {
            get { return _announcementTitle; }
            set { base.SetProperty<string>("AnnouncementTitle", ref _announcementTitle, value); }
        }

        public bool IsSoldOut
        {
            get { return _isSoldOut; }
            set { base.SetProperty<bool>("IsSoldOut", ref _isSoldOut, value); }
        }

        public string SmallImageUrl
        {
            get { return _smallImageUrl; }
            set { base.SetProperty<string>("SmallImageUrl", ref _smallImageUrl, value); }
        }

        public List<string> Tags
        {
            get { return _tags; }
            set { base.SetProperty<List<string>>("Tags", ref _tags, value); }
        }

        public bool ShippingAddressRequired
        {
            get { return _shippingAddressRequired; }
            set { base.SetProperty<bool>("ShippingAddressRequired", ref _shippingAddressRequired, value); }
        }

        public bool IsTipped
        {
            get { return _isTipped; }
            set { base.SetProperty<bool>("IsTipped", ref _isTipped, value); }
        }

        public string Title
        {
            get { return _title; }
            set { base.SetProperty<string>("Title", ref _title, value); }
        }

        public List<Option> Options
        {
            get { return _options; }
            set { base.SetProperty<List<Option>>("Options", ref _options, value); }
        }

        public string Id
        {
            get { return _id; }
            set { base.SetProperty<string>("Id", ref _id, value); }
        }

        public int SoldQuantity
        {
            get { return _soldQuantity; }
            set { base.SetProperty<int>("SoldQuantity", ref _soldQuantity, value); }
        }

        public string LargeImageURL
        {
            get { return _largeImageUrl; }
            set { base.SetProperty<string>("LargeImageURU", ref _largeImageUrl, value); }
        }

        public Division Division
        {
            get { return _division; }
            set { base.SetProperty<Division>("Division", ref _division, value); }
        }

        public string DealURL
        {
            get { return _dealUrl; }
            set { base.SetProperty<string>("DealURL", ref _dealUrl, value); }
        }

        public Says Says
        {
            get { return _says; }
            set { base.SetProperty<Says>("Says", ref _says, value); }
        }

        internal static Deal Parse(XmlNode xmlNode)
        {
            Deal result = null;

            if (xmlNode != null)
            {
                result = new Deal();

                result.AnnouncementTitle = xmlNode.SelectSingleNode("announcementTitle").GetText();

                foreach (XmlNode area in xmlNode.SelectNodes("areas"))
                {
                    result.Areas = area.GetText();
                }

                result.DealURL = xmlNode.SelectSingleNode("dealUrl").GetText();
                result.Division = Division.Parse(xmlNode.SelectSingleNode("division"));
                result.EndAt = xmlNode.SelectSingleNode("endAt").GetDateTime();
                result.HighlightsHTML = xmlNode.SelectSingleNode("highlightsHtml").GetText();
                result.Id = xmlNode.SelectSingleNode("id").GetText();
                result.IsNowDeal = xmlNode.SelectSingleNode("isNowDeal").GetBool();
                result.IsSoldOut = xmlNode.SelectSingleNode("isSoldOut").GetBool();
                result.IsTipped = xmlNode.SelectSingleNode("isTipped").GetBool();
                result.LargeImageURL = xmlNode.SelectSingleNode("largeImageUrl").GetText();
                result.MediumImageURL = xmlNode.SelectSingleNode("mediumImageUrl").GetText();

                foreach (XmlNode merchantNode in xmlNode.SelectNodes("merchant"))
                {
                    Merchant merchant = Merchant.Parse(merchantNode);
                    if (merchant != null) { result.Merchants.Add(merchant); }
                }

                foreach (XmlNode optionNode in xmlNode.SelectNodes("options/option"))
                {
                    Option option = Option.Parse(optionNode);
                    if (option != null) { result.Options.Add(option); }
                }

                result.PitchHTML = xmlNode.SelectSingleNode("pitchHtml").GetText();

                switch (xmlNode.SelectSingleNode("placementPriority").GetText())
                {
                    case "featured": result.PlacementPriority = DealPlacementPriorities.Featured; break;
                    case "side-deal": result.PlacementPriority = DealPlacementPriorities.SideDeal; break;
                    case "nearby": result.PlacementPriority = DealPlacementPriorities.Nearby; break;
                    default: break;
                }

                result.Says = Says.Parse(xmlNode.SelectSingleNode("says"));
                result.ShippingAddressRequired = xmlNode.SelectSingleNode("shippingAddressRequired").GetBool();
                result.SideBarImageURL = xmlNode.SelectSingleNode("sideBarImageUrl").GetText();
                result.SmallImageUrl = xmlNode.SelectSingleNode("smallImageUrl").GetText();
                result.SoldQuantity = xmlNode.SelectSingleNode("soldQuantity").GetInt();
                result.StartAt = xmlNode.SelectSingleNode("startAt").GetDateTime();

                switch (xmlNode.SelectSingleNode("status").GetText())
                {
                    case "closed": result.Status = DealStatus.Closed; break;
                    case "open": result.Status = DealStatus.Open; break;
                    default: break;
                }

                foreach (XmlNode tagNode in xmlNode.SelectNodes(@"tags/tag"))
                {
                    string tag = tagNode.SelectSingleNode("name").GetText();
                    if (tag.HasValue()) { result.Tags.Add(tag); }
                }

                result.TextAd = TextAd.Parse(xmlNode.SelectSingleNode("textAd"));
                result.TippedAt = xmlNode.SelectSingleNode("tippedAt").GetDateTime();
                result.TippingPoint = xmlNode.SelectSingleNode("tippingPoint").GetInt();
                result.Title = xmlNode.SelectSingleNode("title").GetText();

                switch (xmlNode.SelectSingleNode("type").GetText())
                {
                    case "groupon": result.Type = DealTypes.Groupon; break;
                    case "merchant": result.Type = DealTypes.Merchant; break;
                    case "promoted-merchant": result.Type = DealTypes.PromotedMerchant; break;
                    default: break;
                }

                return result;
    
            }

            return result;
        }

    }
}
